package com.vshop.platform.system.crud.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.vshop.framework.core.constant.Const;
import com.vshop.framework.core.util.StreamUtil;
import com.vshop.framework.satoken.helper.LoginHelper;
import com.vshop.platform.system.crud.dao.SysMenuDao;
import com.vshop.platform.system.domain.model.Router;
import com.vshop.platform.system.domain.model.RouterMeta;
import com.vshop.platform.system.domain.model.SysMenuDTO;
import com.vshop.platform.system.domain.vo.SysUserVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import static com.vshop.platform.system.domain.entity.table.SysMenuTableDef.SysMenuTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleMenuTableDef.SysRoleMenuTable;
import static com.vshop.platform.system.domain.entity.table.SysRoleTableDef.SysRoleTable;
import static com.vshop.platform.system.domain.entity.table.SysUserRoleTableDef.SysUserRoleTable;
import static com.vshop.platform.system.domain.entity.table.SysUserTableDef.SysUserTable;

@RequiredArgsConstructor
@Slf4j
@Service
public class AuthSystemService {

    private final SysMenuDao sysMenuDao;

    public SysUserVo getUserById(Long userId) {
        QueryWrapper queryWrapper = QueryWrapper.create()
                .from(SysUserTable)
                .where(SysUserTable.UserId.eq(userId));
        return sysMenuDao.getOneAs(queryWrapper, SysUserVo.class);
    }

    /**
     * 构建前端路由所需要的菜单
     *
     * @param menus 菜单列表
     * @return 路由列表
     */
    public List<Router> buildMenuRouters(List<SysMenuDTO> menus) {
        List<Router> routers = new LinkedList<>();
        for (SysMenuDTO menu : menus) {
            Router router = new Router();
//            String menuType = menu.getMenuType();
            router.setPath(menu.getPath());
            router.setName(menu.getRouterName());
            router.setComponent(menu.getComponent());

            RouterMeta meta = new RouterMeta();
            meta.setTitle(menu.getMenuName());
            meta.setIcon(menu.getIcon());
//            meta.setPerms(menu.getPerms());
//            meta.setIsHide(StrUtil.equals("1", menu.getIsHide()));
//            meta.setIsKeepAlive(StrUtil.equals("1", menu.getIsCache()));
//            meta.setIsKeepAlive(1 == menu.getIsCache());
            meta.setHidden(StrUtil.equals("1", menu.getVisible()));
            meta.setBreadcrumbHidden(StrUtil.equals("1", menu.getBreadcrumbHidden()));
            meta.setLevelHidden(StrUtil.equals("1", menu.getLevelHidden()));
            meta.setDynamicNewTab(StrUtil.equals("1", menu.getDynamicNewTab()));
            meta.setNoClosable(StrUtil.equals("1", menu.getNoClosable()));
            meta.setIsCustomSvg(StrUtil.equals("0", menu.getIsCustomSvg())); // 0自定义
            meta.setNoKeepAlive(1 == menu.getIsCache());
            meta.setActiveMenu("");
            meta.setTarget(menu.getTarget());

            router.setMeta(meta);
            List<SysMenuDTO> cMenus = menu.getChildren();
            if (CollUtil.isNotEmpty(cMenus)) {
                router.setChildren(buildMenuRouters(cMenus));
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 根据用户ID查询菜单
     *
     * @param userId 用户名称
     * @return 菜单列表
     */
    public List<SysMenuDTO> listMenuTreeByUserId(Long userId) {
        QueryWrapper queryWrapper = null;
        if (LoginHelper.isSuperAdmin(userId)) {
            queryWrapper = QueryWrapper.create()
                    .and(SysMenuTable.MenuType.in(Const.MenuTypeDir, Const.MenuTypeMenu))
                    .and(SysMenuTable.Status.eq(Const.StatusNormal))
                    .orderBy(SysMenuTable.ParentId.asc())
                    .orderBy(SysMenuTable.SortNum.asc());
        } else {
                 /*select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
            from SysMenuTable m
            left join sys_role_menu rm on m.menu_id = rm.menu_id
            left join sys_user_role ur on rm.role_id = ur.role_id
            left join sys_role ro on ur.role_id = ro.role_id
            left join sys_user u on ur.user_id = u.user_id
            where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0  AND ro.status = 0
            order by m.parent_id, m.order_num*/

            queryWrapper = QueryWrapper.create()
                    .select(QueryMethods.distinct(SysMenuTable.MenuId, SysMenuTable.ParentId, SysMenuTable.MenuName,
                            SysMenuTable.Path, SysMenuTable.Component, SysMenuTable.QueryParam, SysMenuTable.Visible,
                            SysMenuTable.Status, SysMenuTable.Perms, SysMenuTable.IsFrame, SysMenuTable.IsCache,
                            SysMenuTable.MenuType, SysMenuTable.Icon, SysMenuTable.SortNum, SysMenuTable.CreateTime))
                    .from(SysMenuTable)
                    .leftJoin(SysRoleMenuTable).on(SysMenuTable.MenuId.eq(SysRoleMenuTable.MenuId))
                    .leftJoin(SysRoleMenuTable).on(SysRoleMenuTable.RoleId.eq(SysUserRoleTable.RoleId))
                    .leftJoin(SysRoleTable).on(SysRoleTable.RoleId.eq(SysUserRoleTable.RoleId))
                    .leftJoin(SysUserTable).on(SysUserTable.UserId.eq(SysUserRoleTable.UserId))
                    .where(SysUserTable.UserId.eq(userId))
                    .and(SysMenuTable.MenuType.in("0", "1"))
                    .and(SysMenuTable.Status.eq("0"))
                    .and(SysRoleTable.Status.eq("0"))
                    .orderBy(SysMenuTable.ParentId.asc())
                    .orderBy(SysMenuTable.SortNum.asc());
        }
//        List<SysMenuDTO> menus = new ArrayList<>();

        List<SysMenuDTO> menus = sysMenuDao.listAs(queryWrapper, SysMenuDTO.class);
        return buildMenuTreeByParentId(menus);
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     * @return String
     */
    private List<SysMenuDTO> buildMenuTreeByParentId(List<SysMenuDTO> list) {
        List<SysMenuDTO> returnList = new ArrayList<>();
        for (SysMenuDTO item : list) {
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (item.getParentId() == 0) {
                recursionFn(list, item);
                returnList.add(item);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysMenuDTO> list, SysMenuDTO item) {
        // 得到子节点列表
        List<SysMenuDTO> childList = StreamUtil.filter(list, it -> it.getParentId().equals(item.getMenuId()));
        item.setChildren(childList);
        for (SysMenuDTO itemChild : childList) {
            // 判断是否有子节点
            if (list.stream().anyMatch(it -> it.getParentId().equals(itemChild.getMenuId()))) {
                recursionFn(list, itemChild);
            }
        }
    }
}
